package core

import (
	"fmt"
	"io"
	"net"
	"os/exec"
	"time"
)

// Capture 截图
type Capture struct {
	chCode   int
	path     string // 需要截图的地址
	pushConn net.Conn
}

func NewCapture(chCode int, path string) *Capture {
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", G.Dispatcher.Capture.Host, G.Dispatcher.Capture.Port))
	if err != nil {
		G.Log.Errorf("Can not to connect to [%s:%d]", G.Dispatcher.Capture.Host, G.Dispatcher.Capture.Port)
		return nil
	}
	return &Capture{
		chCode:   chCode,
		path:     path,
		pushConn: conn,
	}
}

// Start CapturePicture 截图
func (o *Capture) Start() {
	G.Log.Infof("Start capture at channel code[%d]", o.chCode)
	// 开启一个截图转换
	args := []string{
		"-rtsp_transport", "tcp",
		"-i", o.path,
		"-ss", "00:00:00",
		"-vframes", "1",
		"-q:v", "2",
		"-vf", "select='eq(pict_type\\,I)'", //  提取关键帧参数
		"-f", "mjpeg",
		//"-",
		"pipe:1",
	}

	cmd := exec.Command(G.App.FFMpeg, args...)
	defer func() {
		G.Log.Info("Kill capture process ", cmd.Process.Pid)
		// 关闭ffmpeg子进程
		if err := cmd.Process.Kill(); err != nil {
			G.Log.Errorf("Kill command error: %v", err)
		}
		// 需要等待子进程关闭，否则子进程会成为僵尸进程
		if err := cmd.Wait(); err != nil {
			G.Log.Errorf("Wait Capture Kill command error: %v", err)
		}
	}()

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		G.Log.Errorf("StdoutPipe err:[%s]", err)
		return
	}
	if err = cmd.Start(); err != nil {
		G.Log.Errorf("Start pipe command err:[%s]", err)
		return
	}
	chNo := o.chCode
	o.pushConn.Write([]byte(fmt.Sprintf("%5d", chNo)))
	ch := make(chan int, 1)

	go func() {
		// 此处需要使用一个缓冲区分批发送
		buf := make([]byte, 1024)
		total := 0
		defer func() {
			o.pushConn.Close()
			return
		}()
		for {
			n, err := stdout.Read(buf)
			if err == io.EOF {
				G.Log.Info("Read capture buf complete")
				break
			} else {
				G.Log.Infof("Send capture buf len[%d]", n)
				o.pushConn.Write(buf[:n])
				total += n
			}
		}
		ch <- total
	}()
	//writtenLen, err := io.Copy(o.pushConn, stdout)
	//if err != nil {
	//	G.Log.Errorf("Copy pipe command err:[%s]", err)
	//}`
	select {
	case result := <-ch:
		G.Log.Infof("Capture has complete send buf and the length is [%d]", result)
	case <-time.After(time.Second * 25):
		o.pushConn.Close()
		G.Log.Infof("Capture has handle channel code [%d] timeout", chNo)
	}
}
